from __future__ import with_statement
from khronos import *

class Queue(Atomic):
    size = AutoPoll(name="queue size")
    content = []
    def __init__(self, *args, **kwargs):
        Atomic.__init__(self, *args, **kwargs)
        Queue.size.initialize(self, value=0, name="queue size")
        
    def status(self):
        return str(self.content)
        
    def initializer(self):
        Queue.size.reset(self, 0)
        self.content = []
        
    def append(self, obj):
        self.content.append(obj)
        self.size = len(self.content)
        
    def next(self):
        try:
            obj = self.content.pop(0)
        except IndexError:
            self.size = -1
            raise
        else:
            self.size = len(self.content)
            return obj
            
class Producer(Atomic):
    @chain
    def initializer(self):
        queue = self.find(".q")
        rng = self.get_rng()
        while True:
            yield rng.uniform(5, 10) * MINUTE
            queue.append(rng.choice("abcdefgh"))
            
class Consumer(Atomic):
    state = "IDLE"
    def status(self):
        return self.state
        
    @chain
    def initializer(self):
        queue = self.find(".q")
        rng = self.get_rng()
        
        yield 0.0
        while True:
            self.state = "WAITING"
            yield Queue.size.pollvar(queue) >= 10
            self.state = "CONSUMING"
            while True:
                yield rng.uniform(4, 10) * MINUTE
                try:
                    queue.next()
                except IndexError:
                    break
                    

def build():
    m = Composite("root", children=[Queue("q"), Producer("p"), Consumer("c")])
    k = Khronos(m)
    return k, m

def main():
    k, m = build()
    k.single_run(DAY)
    
k, m = build()
